#! /usr/bin/env python
#coding=utf-8
'''
建造者模式的Python3 实现
'''

from abc import ABCMeta,abstractmethod


class Product(metaclass=ABCMeta):
    '''
    抽象产品
    '''
    
    def __init__(self):
        self.parts = []
    
    @abstractmethod
    def doSomething(self):
        pass
        
class ConcreteProduct1(Product):
    '''
    具体产品1
    '''

    def doSomething(self):
        print('ConcreteProduct1')
        for part in self.parts:
            print(part)
            
class ConcreteProduct2(Product):
    '''
    具体产品2
    '''

    def doSomething(self):
        print('ConcreteProduct2')
        for part in self.parts:
            print(part)
            

class Builder(metaclass=ABCMeta):
    '''
    抽象建造者
    '''
    
    @abstractmethod
    def setPart(self):
        pass
        
    @abstractmethod
    def buildProduct(self):
        pass
        
        
class ConcreteBuilder1(Builder):
    '''
    具体建造者1
    '''
    
    def __init__(self):
        super(self.__class__, self).__init__()
        self.product = ConcreteProduct1()
    
    def setPart(self):
        self.product.parts.append('begin')
        self.product.parts.append('run')
        self.product.parts.append('stop')
        
    def buildProduct(self):
        return self.product
        
        
class ConcreteBuilder2(Builder):
    '''
    具体建造者2
    '''
    
    def __init__(self):
        super(self.__class__, self).__init__()
        self.product = ConcreteProduct2()
    
    def setPart(self):
        self.product.parts.append('cycle')
        self.product.parts.append('left')
        self.product.parts.append('right')
        
    def buildProduct(self):
        return self.product
        
class Director():
    '''
    导演类
    '''
    def __init__(self):
        self.builder1 = ConcreteBuilder1()
        self.builder2 = ConcreteBuilder2()
    
    def getProduct1(self):
        self.builder1.setPart()
        return self.builder1.buildProduct()
        
    def getProduct2(self):
        self.builder2.setPart()
        return self.builder2.buildProduct()



if __name__ == '__main__':
    director = Director()
    director.getProduct1().doSomething()
    director.getProduct2().doSomething()
    
    
    